package jvDeformation.gui;

import java.awt.Choice;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;


public class ComboBox<E> implements Collection<E>{

	
	final Choice choice = new Choice();
	final List<E> collection = new ArrayList<E>();
	
	public ComboBox() {
		initListener();
	}
	
	public ComboBox(E[] array) {
		for (E e : array) {
			collection.add(e);
		}
		update();
		initListener();
	}
	
	private void initListener(){
		choice.addItemListener(new ItemListener() {
			
			@Override
			public void itemStateChanged(ItemEvent e) {
				itemEvent(e);
			}
		});
	}
	
	public void select(E e){
		if (collection.contains(e)) {
			choice.select(collection.indexOf(e));
		}
	}
	
	private List<ActionListener> actionListeners = new ArrayList<ActionListener>();
	public boolean addActionListener(ActionListener listener){
		return actionListeners.add(listener);
	}
	
	public boolean removeActionListener(Object listener){
		return actionListeners.remove(listener);
	}
	
	private void itemEvent(ItemEvent e){
		if (e.getStateChange() == ItemEvent.SELECTED) {
			ActionEvent ae = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, e.getItem().toString());
			for (ActionListener listener : actionListeners) {
				listener.actionPerformed(ae);
			}
		}
	}

	public Component getComponent(){
		return choice;
	}
	
	public E getSelected(){
		int selected=choice.getSelectedIndex();
		if (selected >= 0) {
			return collection.get(selected);
		}
		return null;
	}
	
	private void update(){
		int selected=Math.max(0,choice.getSelectedIndex());
		for (E e : collection) {
			choice.add(e.toString());
		}
		try{
			choice.select(selected);
		}catch(IllegalArgumentException e){
			choice.select(0);
		}
	}

	/**
	 * @return
	 * @see java.util.Collection#size()
	 */
	public int size() {
		return collection.size();
	}

	/**
	 * @return
	 * @see java.util.Collection#isEmpty()
	 */
	public boolean isEmpty() {
		return collection.isEmpty();
	}

	/**
	 * @param o
	 * @return
	 * @see java.util.Collection#contains(java.lang.Object)
	 */
	public boolean contains(Object o) {
		return collection.contains(o);
	}

	/**
	 * @return
	 * @see java.util.Collection#iterator()
	 */
	public Iterator<E> iterator() {
		return collection.iterator();
	}

	/**
	 * @return
	 * @see java.util.Collection#toArray()
	 */
	public Object[] toArray() {
		return collection.toArray();
	}

	/**
	 * @param a
	 * @return
	 * @see java.util.Collection#toArray(java.lang.Object[])
	 */
	public <T> T[] toArray(T[] a) {
		return collection.toArray(a);
	}

	/**
	 * @param e
	 * @return
	 * @see java.util.Collection#add(java.lang.Object)
	 */
	public boolean add(E e) {
		boolean add = collection.add(e);
		update();
		return add;
	}

	/**
	 * @param o
	 * @return
	 * @see java.util.Collection#remove(java.lang.Object)
	 */
	public boolean remove(Object o) {
		boolean remove = collection.remove(o);
		update();
		return remove;
	}

	/**
	 * @param c
	 * @return
	 * @see java.util.Collection#containsAll(java.util.Collection)
	 */
	public boolean containsAll(Collection<?> c) {
		return collection.containsAll(c);
	}

	/**
	 * @param c
	 * @return
	 * @see java.util.Collection#addAll(java.util.Collection)
	 */
	public boolean addAll(Collection<? extends E> c) {
		boolean addAll = collection.addAll(c);
		update();
		return addAll;
	}

	/**
	 * @param c
	 * @return
	 * @see java.util.Collection#removeAll(java.util.Collection)
	 */
	public boolean removeAll(Collection<?> c) {
		boolean removeAll = collection.removeAll(c);
		update();
		return removeAll;
	}

	/**
	 * @param c
	 * @return
	 * @see java.util.Collection#retainAll(java.util.Collection)
	 */
	public boolean retainAll(Collection<?> c) {
		boolean retainAll = collection.retainAll(c);
		update();
		return retainAll;
	}

	/**
	 * 
	 * @see java.util.Collection#clear()
	 */
	public void clear() {
		collection.clear();
		update();
	}

	/**
	 * @param o
	 * @return
	 * @see java.util.Collection#equals(java.lang.Object)
	 */
	public boolean equals(Object o) {
		return collection.equals(o);
	}

	/**
	 * @return
	 * @see java.util.Collection#hashCode()
	 */
	public int hashCode() {
		return collection.hashCode();
	}

}
